package com.base.param;

import cn.hutool.core.collection.CollUtil;
import lombok.Getter;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.schema.Column;

import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public enum SqlKeyword {
    //AND("AND"),
    //OR("OR"),
    //NOT("NOT"),
    IN("IN", (whereParam, valueIsPlaceholder) -> {
        final Column left = new Column(whereParam.getColumnCode());
        Stream<?> stream;
        final Object value = whereParam.getValue();
        if (value instanceof Collection) {
            if (CollUtil.isEmpty(((Collection<?>) value))) {
                return null;
            }
            stream = ((Collection<?>) value).stream();
        } else {
            stream = Stream.of(String.valueOf(value).split(","));
        }
        final List<StringValue> values = stream.map(val -> new StringValue(String.valueOf(val))).collect(Collectors.toList());
        ExpressionList right = new ParenthesedExpressionList(values);
        return new InExpression(left, right);
    }),
    NOT_IN("NOT IN", (whereParam, valueIsPlaceholder) -> {
        final Column left = new Column(whereParam.getColumnCode());
        Stream<?> stream;
        final Object value = whereParam.getValue();
        if (value instanceof Collection) {
            if (CollUtil.isEmpty(((Collection<?>) value))) {
                return null;
            }
            stream = ((Collection<?>) value).stream();
        } else {
            stream = Stream.of(String.valueOf(value).split(","));
        }
        final List<StringValue> values = stream.map(val -> new StringValue(String.valueOf(val))).collect(Collectors.toList());
        ExpressionList right = new ParenthesedExpressionList(values);
        return new InExpression(left, right).withNot(true);
    }),
    LIKE("LIKE", (whereParam, valueIsPlaceholder) -> new LikeExpression().withLeftExpression(new Column(whereParam.getColumnCode())).withRightExpression(valueIsPlaceholder ? new JdbcParameter() : new StringValue(String.valueOf(whereParam.getValue())))),
    NOT_LIKE("NOT LIKE", (whereParam, valueIsPlaceholder) -> new LikeExpression().withLeftExpression(new Column(whereParam.getColumnCode())).withRightExpression(valueIsPlaceholder ? new JdbcParameter() : new StringValue(String.valueOf(whereParam.getValue()))).withNot(true)),
    EQ("=", (whereParam, valueIsPlaceholder) -> new EqualsTo(new Column(whereParam.getColumnCode()), valueIsPlaceholder ? new JdbcParameter() : new StringValue(String.valueOf(whereParam.getValue())))),
    NE("<>", (whereParam, valueIsPlaceholder) -> new NotEqualsTo(new Column(whereParam.getColumnCode()), valueIsPlaceholder ? new JdbcParameter() : new StringValue(String.valueOf(whereParam.getValue())))),
    GT(">", (whereParam, valueIsPlaceholder) -> new GreaterThan().withLeftExpression(new Column(whereParam.getColumnCode())).withRightExpression(valueIsPlaceholder ? new JdbcParameter() : new StringValue(String.valueOf(whereParam.getValue())))),
    GE(">=", (whereParam, valueIsPlaceholder) -> new GreaterThanEquals().withLeftExpression(new Column(whereParam.getColumnCode())).withRightExpression(valueIsPlaceholder ? new JdbcParameter() : new StringValue(String.valueOf(whereParam.getValue())))),
    LT("<", (whereParam, valueIsPlaceholder) -> new MinorThan().withLeftExpression(new Column(whereParam.getColumnCode())).withRightExpression(valueIsPlaceholder ? new JdbcParameter() : new StringValue(String.valueOf(whereParam.getValue())))),
    LE("<=", (whereParam, valueIsPlaceholder) -> new MinorThanEquals().withLeftExpression(new Column(whereParam.getColumnCode())).withRightExpression(valueIsPlaceholder ? new JdbcParameter() : new StringValue(String.valueOf(whereParam.getValue())))),
    IS_NULL("IS NULL", (whereParam, valueIsPlaceholder) -> new IsNullExpression().withLeftExpression(new Column(whereParam.getColumnCode()))),
    IS_NOT_NULL("IS NOT NULL", (whereParam, valueIsPlaceholder) -> new IsNullExpression().withLeftExpression(new Column(whereParam.getColumnCode())).withNot(true)),

    //GROUP_BY("GROUP BY"),
    //HAVING("HAVING"),
    //ORDER_BY("ORDER BY"),
    //EXISTS("EXISTS"),
    //NOT_EXISTS("NOT EXISTS"),

    //BETWEEN("BETWEEN"),
    //NOT_BETWEEN("NOT BETWEEN"),

    //ASC("ASC"),
    //DESC("DESC")
    ;
    @Getter
    private final String keyword;
    @Getter
    private final BiFunction<WhereParam, Boolean, Expression> expressionFunction;


    SqlKeyword(String keyword, BiFunction<WhereParam, Boolean, Expression> expressionFunction) {
        this.keyword = keyword;
        this.expressionFunction = expressionFunction;
    }
}